﻿Imports System.Runtime.InteropServices
Imports System.Drawing.Imaging
Imports System.Drawing
Imports System.Windows.Forms

Public Class clsVsdr
#Region " IDisposable Support "
    Implements IDisposable
    Private disposedValue As Boolean = False        ' 偵測多餘的呼叫
    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' 關閉檢查連線狀態
                If IsNothing(Me._cbTimer) = False Then Me._cbTimer.Dispose()
                ' 關閉CKE AVI EXPORT
                AviExportStop()
                ' 關閉sock連線
                SockDispose()
                ' 關閉PHHCodec
                ClosePHHCodec()
            End If
            ' TODO: 釋放共用的 Unmanaged 資源
        End If
        Me.disposedValue = True
    End Sub
    ' 由 Visual Basic 新增此程式碼以正確實作可處置的模式。
    Public Sub Dispose() Implements IDisposable.Dispose
        ' 請勿變更此程式碼。在以上的 Dispose 置入清除程式碼 (ByVal 視為布林值處置)。
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

#Region " [引用] "
    '********* 加密 ***********
    Private Declare Sub EncodeBuf Lib "EncodePwd.dll" (ByRef pBuf As Byte, ByVal BufSize As UInt32)
    Private Declare Sub Writestream Lib "EncodePwd.dll" (ByRef pBuf As Byte, ByVal BufSize As UInt32)
    Private Declare Sub Initstream Lib "EncodePwd.dll" ()
    Private Declare Sub Endstream Lib "EncodePwd.dll" ()

    '********* Codec ***********
    Private Declare Function OpenPHHCodec Lib "CodecManager.dll" () As Boolean
    Private Declare Function ClosePHHCodec Lib "CodecManager.dll" () As Boolean
    Private Declare Function PHHCodec Lib "CodecManager.dll" ( _
                                        ByRef inBmpHeader As BITMAPINFOHEADER, _
                                        ByRef inBuf As Byte, _
                                        ByRef retBuf As Byte, _
                                        ByRef PreBuf As Byte) As Integer
    'Private Declare Function PHHCodec Lib "CodecManager.dll" ( _
    '                                   ByRef inBmpHeader As BITMAPINFOHEADER, _
    '                                   ByVal inBuf As Integer, _
    '                                   ByVal retBuf As Integer, _
    '                                   ByVal PreBuf As Integer) As Integer
#End Region

#Region " [Timer CallBack] "
    Private WithEvents _cbTimer As System.Timers.Timer = Nothing

    ' 重新連線
    Private Sub _cbTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles _cbTimer.Elapsed
        ' 檢查連線狀態
        checkConnect()
    End Sub
#End Region

#Region " [WinSock] "
    Private TcpBuffer() As Byte
    Private _syncSock As Object = Nothing
    Private WithEvents _mySock As clsWinSock = Nothing

    ' 關閉sock連線
    Private Sub SockDispose()
        SyncLock Me._syncSock
            If IsNothing(Me._mySock) = False Then
                Me._mySock.Dispose()
                Me._mySock = Nothing
            End If
        End SyncLock
    End Sub
    ' sock關閉
    Private Sub mySock_SckClose(ByVal sender As clsWinSock, ByVal IP As String, ByVal PORT As Integer, ByVal RemoteBreak As Boolean) Handles _mySock.SckClose
        ' 關閉sock連線
        SockDispose()
        RaiseEvent SckClose(Me, IP, PORT, Me._VsdrData.VsdrName, RemoteBreak)
    End Sub

    Private Sub mySock_SckConnect(ByVal sender As clsWinSock, ByVal IP As String, ByVal PORT As Integer) Handles _mySock.SckConnect
        Erase Me.TcpBuffer
        RaiseEvent SckConnect(Me, IP, PORT)
    End Sub

    Private Sub mySock_SckDataArrival(ByVal sender As clsWinSock, ByVal Data() As Byte) Handles _mySock.SckDataArrival
        Dim LastBuffLen As Integer = 0
        If IsNothing(Me.TcpBuffer) = False Then
            LastBuffLen = TcpBuffer.Length
        End If

        ReDim Preserve TcpBuffer(LastBuffLen + Data.Length - 1)
        Array.Copy(Data, 0, Me.TcpBuffer, LastBuffLen, TcpBuffer.Length - LastBuffLen)

        ' 處理資料
        Me.DataWork()
    End Sub

    ' sock錯誤
    Private Sub mySock_SckError(ByVal sender As clsWinSock, ByVal Description As String) Handles _mySock.SckError
        ' 關閉sock連線
        SockDispose()
        RaiseEvent SckError(Me, Description)
    End Sub
#End Region

#Region " [事件]"
    ' 警報事件
    Public Event Alarm(ByVal sender As clsVsdr, ByVal ch As Byte, ByVal Type As Byte, ByVal IsAlarm As Boolean)
    ' 警報名稱設定
    Public Event AlarmName(ByVal sender As clsVsdr, ByVal AlarmState() As stAlarmState)
    ' 登入失敗
    Public Event LoginFail(ByVal sender As clsVsdr, ByVal IP As String, ByVal PORT As Integer)
    ' 遠端HDD錄影時間
    Public Event RecRange(ByVal sender As clsVsdr, ByVal Ch As Byte, ByVal ScanRate As Double, ByVal RecStUtc As Date, ByVal RecEndUtc As Date, ByVal HddPresent As Single)
    ' 有人正在playback
    Public Event PlayBackUsing(ByVal sender As clsVsdr, ByVal IP As String, ByVal PORT As Integer)
    ' 遠端主機資訊
    Public Event VsdrInfo(ByVal sender As clsVsdr, ByVal IP As String, ByVal PORT As Integer, ByVal VsdrName As String, ByVal TotCh As UInt16)
    ' SOCK 嘗試連線中
    Public Event SckTryConnect(ByVal sender As clsVsdr, ByVal IP As String, ByVal PORT As Integer)
    ' SOCK 已斷線
    Public Event SckClose(ByVal sender As clsVsdr, ByVal IP As String, ByVal PORT As Integer, ByVal VsdrName As String, ByVal RemoteBreak As Boolean)
    ' SOCK 已連線
    Public Event SckConnect(ByVal sender As clsVsdr, ByVal IP As String, ByVal PORT As Integer)
    ' SOCK Error
    Public Event SckError(ByVal sender As clsVsdr, ByVal Description As String)
    ' 需要登入密碼
    Public Event NeedLogin(ByVal sender As clsVsdr)
    ' 顯示影像視窗
    Public Event ShowVdoWindow(ByVal sender As clsVsdr, ByVal PlayMode As enumPlayMode)
#End Region

#Region " [屬性] "
    Property IsFullMode() As Boolean
        Get
            Return Me._IsFullMode
        End Get
        Set(ByVal value As Boolean)
            Me._IsFullMode = value
        End Set
    End Property
    WriteOnly Property SetPicFull() As PictureBox
        Set(ByVal value As PictureBox)
            Me._PicFull = value
        End Set
    End Property
    ' 設定顯示圖片物件
    WriteOnly Property SetPics() As PictureBox()
        Set(ByVal value As PictureBox())
            SyncLock Me._syncPics
                Me._Pics = value
                If IsNothing(value) Then
                    Select Case Me._PlayMode
                        Case enumPlayMode.LiveMode
                            ' 關閉LIVE圖片
                            cmdSend(enumCmd.CloseLive)

                        Case enumPlayMode.BackMode
                            ' 關閉PLAY BACL圖片
                            cmdSend(enumCmd.CloseBack)
                    End Select
                End If
            End SyncLock
        End Set
    End Property
    ' 設定顯示時間物件
    WriteOnly Property SetLbls() As Label()
        Set(ByVal value As Label())
            SyncLock Me._syncPics
                Me._Lbls = value
            End SyncLock
        End Set
    End Property
    ' IP
    ReadOnly Property IP() As String
        Get
            Return Me._IP
        End Get
    End Property
    ' PORT
    ReadOnly Property PORT() As Integer
        Get
            Return Me._PORT
        End Get
    End Property
    ' 連線狀態
    ReadOnly Property Connected() As Boolean
        Get
            Return IsNothing(Me._mySock) = False AndAlso Me._mySock.Connected
        End Get
    End Property
    ' VSDR資訊
    ReadOnly Property VsdrData() As stVsdrData
        Get
            Return Me._VsdrData
        End Get
    End Property
    ' 全部CH數量
    ReadOnly Property TotCh() As UInt16
        Get
            Return Me._VsdrData.TotCh
        End Get
    End Property
    ' 全部CH數量BitMask
    ReadOnly Property TotChBitMask() As UInt32
        Get
            Dim UIntTotCh As UInt32 = 0
            For i As UInt32 = 0 To (Me._VsdrData.TotCh - 1)
                UIntTotCh += (2 ^ i)
            Next
            Return UIntTotCh
        End Get
    End Property
    ' DVR名稱
    ReadOnly Property VsdrName() As String
        Get
            Return Me._VsdrData.VsdrName
        End Get
    End Property
    ' 播放模式
    Property PlayMode() As enumPlayMode
        Get
            Return Me._PlayMode
        End Get
        Set(ByVal value As enumPlayMode)
            Me._PlayMode = value
            Select Case value
                Case enumPlayMode.LiveMode
                    cmdSend(enumCmd.QryLiveInstId)

                Case enumPlayMode.BackMode
                    cmdSend(enumCmd.PlayBack)
            End Select
        End Set
    End Property
    ' TTL功能
    ReadOnly Property TTLFn() As Boolean
        Get
            Return Me._TTLFn
        End Get
    End Property
    ' PTZ功能
    ReadOnly Property PTZFn() As Boolean
        Get
            Return Me._PTZFn
        End Get
    End Property
#End Region

#Region " [方法] "
    ' VSDR連線
    Public Sub Connect(ByVal IP As String, ByVal PORT As Integer, Optional ByVal Pwd As String = "99999999")
        Me._IP = IP
        Me._PORT = PORT
        Me._defPwd = Pwd

        Me._cbTimer = New System.Timers.Timer(2000)
        Me._cbTimer.Start()
    End Sub
    ' 影像開關
    Private _SelCh As UInt32 = &HFFFF
    Public Sub VideoSelect(ByVal SelCh As UInt32)
        Console.WriteLine("影像開關 VideoSelect = {0}", SelCh)
        Me._SelCh = SelCh
        Dim SelMask() As Byte = System.BitConverter.GetBytes(Me._SelCh)
        If IsNothing(SelMask) = False AndAlso SelMask.Length < 5 Then
            Me._NowSelCh(0) = SelMask(0)
            Me._NowSelCh(1) = SelMask(1)
            Me._NowSelCh(2) = 0 'SelMask(2)
            Me._NowSelCh(3) = 0 'SelMask(3)

            '影像開關
            cmdSend(enumCmd.VideoSel)
        End If
    End Sub
    '遠端撥放控制
    Public Sub cmdPlayCtrl(ByVal PlayCtrl As enumPlayCtrl, Optional ByVal QryTime As Date = Nothing)
        Dim SendCMD(&H23) As Byte
        Dim idJob As Byte
        Dim PlayAction As Byte

        Select Case PlayCtrl
            Case enumPlayCtrl.FastBackward  '<<
                idJob = &H1
                PlayAction = &H3
            Case enumPlayCtrl.Backward  '<
                idJob = &H1
                PlayAction = &H1
            Case enumPlayCtrl.STOP  'STOP
                idJob = &H2
                PlayAction = &H0
            Case enumPlayCtrl.Forward  '>
                idJob = &H1
                PlayAction = &H0
            Case enumPlayCtrl.FastForward  '>>
                idJob = &H1
                PlayAction = &H2
            Case enumPlayCtrl.TimeSearch  'Time Search
                If IsNothing(QryTime) = False AndAlso QryTime <> Date.MinValue Then
                    idJob = &H4
                    PlayAction = &H2
                    '時間總秒數
                    If QryTime > UtcStart Then
                        Dim iUtc As UInt32 = DateDiff(DateInterval.Second, UtcStart, QryTime)
                        Dim bUtc() As Byte = BitConverter.GetBytes(iUtc)
                        SendCMD(&H1C) = bUtc(0)
                        SendCMD(&H1D) = bUtc(1)
                        SendCMD(&H1E) = bUtc(2)
                        SendCMD(&H1F) = bUtc(3)
                    End If
                End If
        End Select

        SendCMD(&H0) = &H2A
        SendCMD(&H1) = &H18
        SendCMD(&H2) = &H43
        SendCMD(&H3) = &H1
        SendCMD(&H4) = &H14
        SendCMD(&H5) = &H0
        SendCMD(&H6) = &H0
        SendCMD(&H7) = &H0
        SendCMD(&H8) = &H14
        SendCMD(&H9) = &H0
        SendCMD(&HA) = &H0
        SendCMD(&HB) = &H0
        SendCMD(&HC) = &HF4
        SendCMD(&HD) = &HFF
        SendCMD(&HE) = &HF8
        SendCMD(&HF) = &HD6

        SendCMD(&H10) = enumPlayMode.BackMode '表示PLAYBACK
        SendCMD(&H11) = &H0
        SendCMD(&H12) = &H1
        SendCMD(&H13) = &H5
        SendCMD(&H14) = &H0
        SendCMD(&H15) = &H0
        SendCMD(&H16) = &H0
        SendCMD(&H17) = &H0
        SendCMD(&H18) = idJob
        SendCMD(&H19) = &H0
        SendCMD(&H1A) = PlayAction
        SendCMD(&H1B) = &H0

        '如果為連線狀態
        If IsNothing(Me._mySock) = False AndAlso Me._mySock.Connected Then
            '傳送資料
            Me._mySock.Send(SendCMD)
        End If
    End Sub
    ' PTZ控制
    Public Enum enumPtzCtrl As Byte
        Titl_Up
        Titl_Down
        Pan_Left
        Pan_Right
        Focus_Near
        Focus_Far
        Zoom_In
        Zoom_Out
        Iris_Open
        Iris_Close
        Auto_Focus
        Auto_Iris
        Auto_Pan
        OSD_Show
    End Enum
    ' PTZ CTRL
    Public Sub cmdPtzCtl(ByVal Cmd As enumPtzCtrl, ByVal MoveSpeed As Integer, ByVal IsOn As Boolean)
        If MoveSpeed < 0 Then MoveSpeed = 0
        If MoveSpeed > 100 Then MoveSpeed = 100
        MoveSpeed = CByte(MoveSpeed)
        Dim CtrlOn As Byte = IIf(IsOn, 1, 0)
        If CtrlOn = 0 Then MoveSpeed = 0

        '開始PTZ控制命令
        Dim SendCMD(&H41) As Byte

        SendCMD(&H0) = &H2A
        SendCMD(&H1) = &H18
        SendCMD(&H2) = &H43
        SendCMD(&H3) = &H1
        SendCMD(&H4) = &H14
        SendCMD(&H5) = &H0
        SendCMD(&H6) = &H0
        SendCMD(&H7) = &H0
        SendCMD(&H8) = &H32
        SendCMD(&H9) = &H0
        SendCMD(&HA) = &H0
        SendCMD(&HB) = &H0
        SendCMD(&HC) = &H16
        SendCMD(&HD) = &HF
        SendCMD(&HE) = &HA1
        SendCMD(&HF) = &H53

        SendCMD(&H10) = &H3
        SendCMD(&H11) = &H0
        SendCMD(&H12) = &H0
        SendCMD(&H13) = &H3
        SendCMD(&H14) = &H0
        SendCMD(&H15) = &H0
        SendCMD(&H16) = &H0
        SendCMD(&H17) = &H0
        SendCMD(&H18) = &HFF
        SendCMD(&H19) = &HFF
        SendCMD(&H1A) = &H0
        SendCMD(&H1B) = &H0
        SendCMD(&H1C) = &H0
        SendCMD(&H1D) = &H0
        SendCMD(&H1E) = &H0
        SendCMD(&H1F) = &H0
        SendCMD(&H20) = &H1E
        SendCMD(&H21) = &H0
        SendCMD(&H22) = &H0
        SendCMD(&H23) = &H0
        SendCMD(&H24) = &H83
        SendCMD(&H25) = &H0
        SendCMD(&H26) = &H1E
        SendCMD(&H27) = &H0
        SendCMD(&H28) = &H0
        SendCMD(&H29) = &H0

        Select Case Cmd
            Case enumPtzCtrl.Titl_Up        ' "向上"
                SendCMD(&H2A) = &H28        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = MoveSpeed   '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Titl_Down      ' "向下"
                SendCMD(&H2A) = &H29        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = MoveSpeed   '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Pan_Left       ' "向左"
                SendCMD(&H2A) = &H2A        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = MoveSpeed   '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Pan_Right      ' "向右"
                SendCMD(&H2A) = &H2B        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = MoveSpeed   '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Focus_Near     ' "焦距拉近"
                SendCMD(&H2A) = &H22        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Focus_Far      ' "焦距拉遠"
                SendCMD(&H2A) = &H23        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Zoom_In        ' "近看"
                SendCMD(&H2A) = &H20        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Zoom_Out       ' "遠看"
                SendCMD(&H2A) = &H21        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Iris_Open      ' "光圈放大"
                SendCMD(&H2A) = &H24        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Iris_Close     ' "光圈縮小"
                SendCMD(&H2A) = &H25        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Auto_Focus     ' "自動對焦"
                SendCMD(&H2A) = &H1E        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Auto_Iris      ' "自動光圈"
                SendCMD(&H2A) = &H1F        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.Auto_Pan       ' "自動旋轉"
                SendCMD(&H2A) = &H10        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0

            Case enumPtzCtrl.OSD_Show       ' "OSD 顯示"
                SendCMD(&H2A) = &H59        '動作
                SendCMD(&H2B) = &H40        '動作
                SendCMD(&H2C) = CtrlOn      '1=On
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0         '左右移動速度 0-100
                SendCMD(&H2F) = &H0
                SendCMD(&H30) = &H0         '上下移動速度 0-100
                SendCMD(&H31) = &H0
        End Select

        SendCMD(&H32) = &H1
        SendCMD(&H33) = &H0
        SendCMD(&H34) = &H0
        SendCMD(&H35) = &H0
        SendCMD(&H36) = &H0
        SendCMD(&H37) = &H0
        SendCMD(&H38) = &H0
        SendCMD(&H39) = &H0
        SendCMD(&H3A) = &H0
        SendCMD(&H3B) = &H0
        SendCMD(&H3C) = &H0
        SendCMD(&H3D) = &H0
        SendCMD(&H3E) = &H0
        SendCMD(&H3F) = &H0
        SendCMD(&H40) = &H0
        SendCMD(&H41) = &H0

        '如果為連線狀態
        If IsNothing(Me._mySock) = False AndAlso Me._mySock.Connected Then
            '傳送資料
            Me._mySock.Send(SendCMD)
        End If
    End Sub
    ' 選取PTZ攝影機
    Public Sub cmdPtzChSelect(ByVal SelChNum As Byte)
        Dim SendCMD(&H43) As Byte

        SendCMD(&H0) = &H2A
        SendCMD(&H1) = &H18
        SendCMD(&H2) = &H43
        SendCMD(&H3) = &H1
        SendCMD(&H4) = &H14
        SendCMD(&H5) = &H0
        SendCMD(&H6) = &H0
        SendCMD(&H7) = &H0
        SendCMD(&H8) = &H34
        SendCMD(&H9) = &H0
        SendCMD(&HA) = &H0
        SendCMD(&HB) = &H0
        SendCMD(&HC) = &HCA
        SendCMD(&HD) = &H50
        SendCMD(&HE) = &HCA
        SendCMD(&HF) = &H76

        SendCMD(&H10) = &H3
        SendCMD(&H11) = &H0
        SendCMD(&H12) = &H0
        SendCMD(&H13) = &H3
        SendCMD(&H14) = &H0
        SendCMD(&H15) = &H0
        SendCMD(&H16) = &H0
        SendCMD(&H17) = &H0
        SendCMD(&H18) = &HFF
        SendCMD(&H19) = &HFF
        SendCMD(&H1A) = &H0
        SendCMD(&H1B) = &H0
        SendCMD(&H1C) = &H0
        SendCMD(&H1D) = &H0
        SendCMD(&H1E) = &H0
        SendCMD(&H1F) = &H0

        SendCMD(&H20) = &H20
        SendCMD(&H21) = &H0
        SendCMD(&H22) = &H0
        SendCMD(&H23) = &H0
        SendCMD(&H24) = &H82
        SendCMD(&H25) = &H0
        SendCMD(&H26) = &H20
        SendCMD(&H27) = &H0
        SendCMD(&H28) = &H0
        SendCMD(&H29) = &H0
        SendCMD(&H2A) = &H3
        SendCMD(&H2B) = &H0
        SendCMD(&H2C) = SelChNum    '0=CH1...,15=CH16
        SendCMD(&H2D) = &H0
        SendCMD(&H2E) = SelChNum    '0=CH1...,15=CH16
        SendCMD(&H2F) = &H0

        SendCMD(&H30) = &H0
        SendCMD(&H31) = &H0
        SendCMD(&H32) = &HFF
        SendCMD(&H33) = &HFF
        SendCMD(&H34) = &H0
        SendCMD(&H35) = &H0
        SendCMD(&H36) = &H0
        SendCMD(&H37) = &H0
        SendCMD(&H38) = &H0
        SendCMD(&H39) = &H0
        SendCMD(&H3A) = &H0
        SendCMD(&H3B) = &H0
        SendCMD(&H3C) = &H0
        SendCMD(&H3D) = &H0
        SendCMD(&H3E) = &H0
        SendCMD(&H3F) = &H0

        SendCMD(&H40) = &H0
        SendCMD(&H41) = &H0
        SendCMD(&H42) = &H0
        SendCMD(&H43) = &H0

        '如果為連線狀態
        If IsNothing(Me._mySock) = False AndAlso Me._mySock.Connected Then
            '傳送資料
            Me._mySock.Send(SendCMD)
        End If
    End Sub
    ' 輸入密碼
    Public Sub SendLoginPwd(ByVal PWD As String)
        Me._defPwd = PWD
        Console.WriteLine("... CmdStr => 送出login PWD={0}", PWD)
        '送出login PWD
        cmdSend(enumCmd.Login)
    End Sub
    ' 開始送圖
    Public Sub VdoStart()
        '詢問要圖密碼
        cmdSend(enumCmd.QryPicPwd)
    End Sub
#End Region

#Region " [CKE AviExport Lib]" '給美國CKE AVI輸出用的Lib
    ' VSDR READY STATUS
    Public Enum enumReadyMode
        Empty
        LiveReady               ' LIVE      準備好了
        PlayBackReady           ' PLAY BACK 準備好了
    End Enum
    Private ReadyMode As enumReadyMode = enumReadyMode.Empty
    ' AVI 輸出進度
    Public Event CKE_AviExportIng(ByVal sender As clsVsdr, ByVal FrameTime As Date)
    ' AVI 輸出完成
    Public Event CKE_AviExportComplete(ByVal sender As clsVsdr)
    ' AVI 輸出錯誤
    Public Event CKE_AviExportErr(ByVal sender As clsVsdr)
    ' 錄影檔案找不到
    Public Event CKE_RecNotFind(ByVal sender As clsVsdr, ByVal FrameTime As Date)
    ' TimeSearch TimeOut計時器
    Private _CKE_SearechOK As Boolean = False
    Private _CKE_WaitSearech As Boolean = False
    Private _CKE_SearchStTime As Date
    Private _CKE_SearchTimeOutSec As Integer = 5
    Private WithEvents _cbTimer_SearchTimeOut As System.Timers.Timer = Nothing
    Private Sub _cbTimer_SearchTimeOut_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles _cbTimer_SearchTimeOut.Elapsed
        If Me._CKE_WaitSearech Then
            ' 如果超過5秒找不到錄影檔
            If DateDiff(DateInterval.Second, Me._CKE_SearchStTime, Now) > Me._CKE_SearchTimeOutSec Then
                ' 結束搜尋等待
                Me._CKE_WaitSearech = False
            End If
        End If
    End Sub

    Private _CKE_thAviExport As Threading.Thread = Nothing
    Private _CKE_AviExportOK As Boolean = False
    Private _CKE_StTime As Date
    Private _CKE_EndTime As Date

    ' AVI輸出 Thread
    Private Sub CkeAviExport(ByVal parameter As Object)
        Dim tIP As String = parameter(0)
        Dim tPwd As String = parameter(1)
        Dim tCh As Integer = parameter(2)
        Dim tOutPath As String = parameter(3)


        ' 連線
        Console.WriteLine("連線 {0}", tIP)
        Me.ReadyMode = enumReadyMode.Empty
        Connect(tIP, 6716, tPwd)
        ' 等待 LiveReady
        Do While Me.ReadyMode <> enumReadyMode.LiveReady
            System.Threading.Thread.Sleep(10)
        Loop

        ' 切到 BackMode
        Console.WriteLine("切到 BackMode")
        Me.ReadyMode = enumReadyMode.Empty
        Me.PlayMode = enumPlayMode.BackMode
        ' 等待 PlayBackReady
        Do While Me.ReadyMode <> enumReadyMode.PlayBackReady
            System.Threading.Thread.Sleep(10)
        Loop

        ' 選取輸出CH
        Console.WriteLine("選取輸出CH = {0}", 2 ^ (tCh - 1))
        Me.ReadyMode = enumReadyMode.Empty
        Me.VideoSelect(2 ^ (tCh - 1))
        ' 等待 PlayBackReady
        Do While Me.ReadyMode <> enumReadyMode.PlayBackReady
            System.Threading.Thread.Sleep(10)
        Loop

        ' Time Search
        Console.WriteLine("Time Search {0}", Me._CKE_StTime)
        Me._CKE_SearechOK = False
        Me._CKE_WaitSearech = True
        Me._CKE_SearchStTime = Now
        Me.cmdPlayCtrl(enumPlayCtrl.TimeSearch, Me._CKE_StTime)
        Me._cbTimer_SearchTimeOut = New System.Timers.Timer(1000)
        Me._cbTimer_SearchTimeOut.Start()
        ' 等待 Time Search完成
        Do While Me._CKE_WaitSearech = True
            System.Threading.Thread.Sleep(10)
        Loop
        ' 如果有找到錄影資料
        Me._cbTimer_SearchTimeOut.Dispose()
        If Me._CKE_SearechOK Then

            ' 如果建立AVI檔成功
            If IsNothing(Me.myAvi) Then
                Dim tOutName As String = "[" & tIP & "]_CH" & _
                                         tCh.ToString.Trim & "_" & _
                                         Me._CKE_StTime.ToString("yyyyMMddHHmmss") & "_" & _
                                         Me._CKE_EndTime.ToString("yyyyMMddHHmmss") & ".AVI"

                ' 建立錄影檔名稱
                Dim recName As String = Me.CreateRecName(tOutPath, tOutName)
                If recName <> String.Empty Then
                    ' 建立新錄影檔
                    Me.myAvi = New clsAviRec
                    ' 如果建立新錄影檔成功
                    If Me.myAvi.CreateFile(recName) Then
                        ' 如果建立Video 
                        If Me.CreateVideoOK(Me.myAvi, recName, 320, 240) Then

                            Console.WriteLine("建立新錄影檔 {0}", recName)

                            ' 開始 AVI 輸出
                            Me._CKE_AviExportOK = False
                            Console.WriteLine("開始 AVI 輸出")
                            Me.cmdPlayCtrl(enumPlayCtrl.Forward)
                            ' 等待 AVI 輸出完成
                            Do While Me._CKE_AviExportOK = False
                                System.Threading.Thread.Sleep(10)
                            Loop

                            ' 關閉VIDEO STREAM
                            If IsNothing(Me.myAvi) = False Then
                                Me.myAvi.Dispose()
                                Me.myAvi = Nothing
                            End If

                            ' AVI 輸出完成
                            Console.WriteLine("AVI 輸出完成")
                            RaiseEvent CKE_AviExportComplete(Me)

                        Else
                            Me.myAvi.Dispose()
                            Me.myAvi = Nothing
                            ' AVI 輸出錯誤
                            RaiseEvent CKE_AviExportErr(Me)
                        End If

                    Else
                        Me.myAvi.Dispose()
                        Me.myAvi = Nothing
                        ' AVI 輸出錯誤
                        RaiseEvent CKE_AviExportErr(Me)
                    End If
                Else
                    ' AVI 輸出錯誤
                    RaiseEvent CKE_AviExportErr(Me)
                End If
            End If

        Else
            ' 錄影檔案找不到
            RaiseEvent CKE_RecNotFind(Me, Me._CKE_StTime)
        End If

        ' 關閉VIDEO STREAM
        If IsNothing(Me.myAvi) = False Then
            Me.myAvi.Dispose()
            Me.myAvi = Nothing
        End If
        Me._CKE_thAviExport = Nothing
    End Sub

    ' AVI輸出開始
    Public Sub AviExportSTART(ByVal tIP As String, ByVal tPwd As String, ByVal tCh As Integer, ByVal tStTime As Date, ByVal tEndTime As Date, ByVal tOutPath As String)
        If IsNothing(Me._CKE_thAviExport) Then
            Me._CKE_thAviExport = New Threading.Thread(AddressOf CkeAviExport)
            ' 不要MilliSecond, 時間比對時會比不出來
            Me._CKE_StTime = New Date(tStTime.Year, tStTime.Month, tStTime.Day, tStTime.Hour, tStTime.Minute, tStTime.Second, 0)
            Me._CKE_EndTime = New Date(tEndTime.Year, tEndTime.Month, tEndTime.Day, tEndTime.Hour, tEndTime.Minute, tEndTime.Second, 0)
            Me._CKE_thAviExport.Start(New Object() {tIP, tPwd, tCh, tOutPath})
        End If
    End Sub

    ' AVI輸出停止
    Public Sub AviExportSTOP()
        Me.VideoSelect(0)
        'Me.PlayMode = enumPlayMode.LiveMode

        If IsNothing(Me._CKE_thAviExport) = False Then
            Me._CKE_thAviExport.Abort()
            Me._CKE_thAviExport = Nothing
        End If
        ' 關閉VIDEO STREAM
        If IsNothing(Me.myAvi) = False Then
            Me.myAvi.Dispose()
            Me.myAvi = Nothing
        End If
    End Sub
#End Region

#Region " AviExport"
    Private myAvi As clsAviRec = Nothing
    ' 建立錄影檔名稱
    Private Function CreateRecName(ByVal tOutPath As String, ByVal tOutName As String) As String
        ' 如果AVI輸出路徑不存在
        If My.Computer.FileSystem.DirectoryExists(tOutPath) = False Then
            '建立AVI輸出路徑
            My.Computer.FileSystem.CreateDirectory(tOutPath)
        End If

        ' 如果錄影檔已經存在
        Dim tOutAviFile As String = tOutPath & "\" & tOutName
        tOutAviFile.Replace("\\", " \")
        If My.Computer.FileSystem.FileExists(tOutAviFile) Then
            ' 幹掉錄影檔
            Try
                My.Computer.FileSystem.DeleteFile(tOutAviFile)
            Catch ex As Exception
                Return String.Empty
            End Try
        End If
        Return tOutAviFile
    End Function
    ' - 建立 VIDEO OK -
    Private Function CreateVideoOK(ByRef tAvi As clsAviRec, ByVal recName As String, ByVal w As Integer, ByVal h As Integer) As Boolean
        Dim rtnVal As Boolean = False
        If IsNothing(tAvi) = False Then
            Dim fName As String = My.Computer.FileSystem.GetName(recName).ToUpper.Replace(".AVI", "")
            With tAvi
                ' - 建立 VIDEO -
                ' === 如果沒有寬高，Media Player不會撥 ===
                If w = 0 Then w = 320
                If h = 0 Then h = 240
                ' === 如果沒有寬高，Media Player不會撥 ===

                Dim tVideoInfo As clsAviRec.AVI_STREAM_INFO
                Dim tFPS As Integer = 10 ' 每秒30張
                With tVideoInfo
                    .fccType = clsAviRec.streamtypeVIDEO
                    .dwRate = tFPS
                    .dwScale = 1
                    .rcFrame.left = 0
                    .rcFrame.top = 0
                    .rcFrame.right = w
                    .rcFrame.bottom = h
                    .dwSuggestedBufferSize = w * h * 3
                    ReDim .szName(127)
                    'Dim b() As Byte = System.Text.ASCIIEncoding.UTF8.GetBytes(fName)
                    Dim b() As Byte = System.Text.Encoding.Default.GetBytes(fName)
                    If b.Length > .szName.Length Then
                        Array.Copy(b, 0, .szName, 0, .szName.Length)
                    Else
                        Array.Copy(b, 0, .szName, 0, b.Length)
                    End If
                End With
                Dim bmpHdr As clsAviRec.BITMAPINFOHEADER
                With bmpHdr
                    .biSize = 40
                    .biWidth = w
                    .biHeight = h
                    .biBitCount = 24
                    .biPlanes = 1
                    .biCompression = clsAviRec.enumfccCodec.MJPG
                    '.biCompression = 0 'clsAviRec.enumfccCodec.H264
                End With
                .VideoStreamInfo = tVideoInfo
                .BmpHdr = bmpHdr
                If .CreateVideoStream Then
                    Console.WriteLine("CreateVideoStream OK")
                    rtnVal = True
                End If
            End With
        End If
        Return rtnVal
    End Function
    ' - 建立 AUDIO OK -
    Private Function CreateAudioOK() As Boolean
        Dim rtnVal As Boolean = False
        If IsNothing(Me.myAvi) = False Then
            With Me.myAvi
                ' - 建立 AUDIO -
                Dim tAudioInfo As clsAviRec.AVI_STREAM_INFO = Nothing
                With tAudioInfo
                    .fccType = clsAviRec.streamtypeAUDIO
                    .dwScale = 1                    ' 聲道數
                    .dwRate = 8000                  ' 8K
                    .dwSuggestedBufferSize = 16000  ' 1秒資料量
                    .dwSampleSize = 16              ' 16bit
                End With
                Dim PcmHdr As clsAviRec.PCMWAVEFORMAT
                With PcmHdr
                    .nChannels = 1
                    .wBitsPerSample = 16
                    .nSamplesPerSec = 8000
                    .nBlockAlign = CShort(.nChannels * .wBitsPerSample / 8)
                    .nAvgBytesPerSec = (.nBlockAlign * .nSamplesPerSec)
                    .wFormatTag = clsAviRec.WaveFormatTag.WAVE_FORMAT_PCM
                    .cbSize = 18
                End With
                'WavFmt
                .AudioStreamInfo = tAudioInfo
                .WavFmt = PcmHdr
                If .CreateAudioStream Then
                    Console.WriteLine("CreateAudioStream OK")
                    rtnVal = True
                End If
            End With
        End If
        Return rtnVal
    End Function

    ' BMP轉成JPG
    Private Function BmpToJpeg(ByVal Data() As Byte, ByVal w As Integer, ByVal h As Integer, ByVal FrameTime As Date) As Byte()
        Dim tBmp As New Bitmap(w, h, 0, Imaging.PixelFormat.Format24bppRgb, Nothing)
        Dim ds As Imaging.BitmapData = tBmp.LockBits(New Rectangle(0, 0, tBmp.Width, tBmp.Height), Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb)
        System.Runtime.InteropServices.Marshal.Copy(Data, 0, ds.Scan0, Data.Length)
        tBmp.UnlockBits(ds)
        tBmp.RotateFlip(RotateFlipType.RotateNoneFlipY)

        Dim g As Graphics = Graphics.FromImage(tBmp)
        clsDibImage.ShowCamText(g, 320, 240, FrameTime.ToString("yyyy/MM/dd HH:mm:ss"))
        g.Dispose()


        Dim jMs As New IO.MemoryStream
        tBmp.Save(jMs, Imaging.ImageFormat.Jpeg)
        Dim bJpg() As Byte = jMs.ToArray
        jMs.Dispose()
        Return bJpg
    End Function

    ' 加入影像資料
    Private Sub AddVideoFrame(ByVal Data() As Byte, ByVal FrameTime As Date)
        If IsNothing(Me.myAvi) = False AndAlso Me.myAvi.IsVideoStreamOpen Then
            Dim bJpg() As Byte = BmpToJpeg(Data, 320, 240, FrameTime)
            Dim rtn As Boolean = Me.myAvi.AddVideoFrame(bJpg)
        End If
    End Sub
    ' 加入聲音資料
    Private Sub AddAudioFrame(ByVal Data() As Byte)
        If IsNothing(Me.myAvi) = False AndAlso Me.myAvi.IsAudioStreamOpen Then
            Me.myAvi.AddAudioSample(Data)
        End If
    End Sub
#End Region

#Region "Normal AVI REC"
    Private Const MB As Long = 1000 * 1000
    Private _AviRec As Boolean
    Private _lblHddFreeSpace As Label = Nothing
    Private _lblAviCameras As Label = Nothing
    Private _lblAviFrames As Label = Nothing
    Private _lblAviStatus As Label = Nothing
    Private _HddInfo As System.IO.DriveInfo = Nothing
    Private _AviFrames As UInt32 = 0
    Private _dicAvi As Dictionary(Of Integer, clsAviRec)
    Private _SyncAviRec As New Object

    ' 目前監看的數量
    Private Function CurSelChCount() As Integer
        Dim rtnVal As Integer = 0
        For i As Integer = 0 To Me.TotCh - 1
            If (Me._SelCh And (2 ^ i)) = (2 ^ i) Then
                rtnVal += 1
            End If
        Next
        Return rtnVal
    End Function

    ' 設定AVI輸出狀態顯示物件
    WriteOnly Property SetAviStatusLbls() As Label()
        Set(ByVal value As Label())
            If IsNothing(value) = False AndAlso value.Length = 4 Then
                Me._lblHddFreeSpace = value(0)
                Me._lblAviCameras = value(1)
                Me._lblAviFrames = value(2)
                Me._lblAviStatus = value(3)

                For Each tInfo As System.IO.DriveInfo In My.Computer.FileSystem.Drives
                    If tInfo.Name = "C:\" Then
                        Me._HddInfo = tInfo
                        Exit For
                    End If
                Next

                Me._AviFrames = 0
                Me._lblHddFreeSpace.Text = (Me._HddInfo.TotalFreeSpace / MB).ToString("0.00") & " MB"
                Me._lblAviCameras.Text = Me.CurSelChCount
                Me._lblAviFrames.Text = Me._AviFrames
                Me._lblAviStatus.Text = "Ready"
                Me.CreateAviFile("C:\AVIEXPO")
            End If
        End Set
    End Property
    ' 開始錄影
    Property AviRec() As Boolean
        Get
            Return Me._AviRec
        End Get
        Set(ByVal value As Boolean)
            Me._AviRec = value
        End Set
    End Property
    ' 結束錄影
    Public Sub AviClose()
        Me._AviRec = False
        SyncLock _SyncAviRec
            If IsNothing(Me._dicAvi) = False AndAlso Me._dicAvi.Count > 0 Then
                For Each tAvi As clsAviRec In Me._dicAvi.Values
                    tAvi.Dispose()
                Next
                Me._dicAvi.Clear()
                Me._dicAvi = Nothing
            End If
        End SyncLock
    End Sub
    ' 建立AVI錄影檔
    Private Sub CreateAviFile(ByVal tOutPath As String)
        Dim tCurTime As Date = Now
        Me._dicAvi = New Dictionary(Of Integer, clsAviRec)

        For i As Integer = 0 To Me.TotCh - 1
            If (Me._SelCh And (2 ^ i)) = (2 ^ i) Then
                Dim tOutName As String = "CAM" & (i + 1).ToString.Trim.PadLeft(2, "0") & "_" & tCurTime.ToString("yyyyMMddHHmmss") & ".AVI"

                ' 建立錄影檔名稱
                Dim recName As String = Me.CreateRecName(tOutPath, tOutName)
                If recName <> String.Empty Then
                    ' 建立新錄影檔
                    Dim tAvi = New clsAviRec

                    ' 如果建立新錄影檔成功, 如果建立Video 
                    If tAvi.CreateFile(recName) AndAlso Me.CreateVideoOK(tAvi, recName, 320, 240) Then
                        SyncLock _SyncAviRec
                            Me._dicAvi.Add(i, tAvi)
                        End SyncLock
                    Else
                        tAvi.Dispose()
                    End If
                End If
            End If
        Next
    End Sub
    ' 更新顯示資訊
    Private Delegate Sub ivk_UpdateLblStatus()
    Private Sub UpdateLblStatus()
        Me._AviFrames += 1
        Me._lblHddFreeSpace.Text = (Me._HddInfo.TotalFreeSpace / MB).ToString("0.00") & " MB"
        Me._lblAviFrames.Text = Me._AviFrames
        Me._lblAviStatus.Text = "Write"
    End Sub
    Private Delegate Sub ivk_UpdateLblTxt(ByVal Txt As String)
    Private Sub UpdateLblTxt(ByVal Txt As String)
        Me._lblAviStatus.Text = Txt
    End Sub
    ' 加入影像資料
    Private Sub AddVideoFrame(ByVal ChNo As Integer, ByVal Data() As Byte, ByVal FrameTime As Date)
        ' 更新顯示資訊
        Me._lblAviFrames.Invoke(New ivk_UpdateLblStatus(AddressOf UpdateLblStatus))
        SyncLock _SyncAviRec
            If IsNothing(Me._dicAvi) = False AndAlso Me._dicAvi.ContainsKey(ChNo) Then
                With Me._dicAvi.Item(ChNo)
                    If .IsVideoStreamOpen Then
                        .AddVideoFrame(BmpToJpeg(Data, 320, 240, FrameTime))
                        'Dim bJpg() As Byte = BmpToJpeg(Data, 320, 240, FrameTime)
                        'Dim rtn As Boolean = .AddVideoFrame(bJpg)
                    End If
                End With
            End If
        End SyncLock
        Me._lblAviStatus.Invoke(New ivk_UpdateLblTxt(AddressOf UpdateLblTxt), "Ready")
    End Sub
#End Region

    ' 播放模式
    Public Enum enumPlayMode As Byte
        LiveMode = &H5
        BackMode = &H6
    End Enum
    ' 命令代碼
    Private Enum enumCmd As Integer
        SendLocalName = 0           '[傳送本機名稱]
        QryLiveInstId = 1           '[詢問Live InstId] = LiveView
        QryName = 2                 '[詢問主機名稱]
        QryChInfo = 3               '[詢問各CH資訊]
        DisConnect = 4              '[斷線]
        QryAlarmSet = 5             '[詢問各alm設定]
        QryPicFormat = 6            '[詢問圖片格式]
        QryPicPwd = 7               '[詢問要圖密碼]
        SendLocalGuid = 8           '[回應本機GUID]
        VideoSel = 9                '[影像開關]
        QryKeyFrame = 10            '[詢問KeyFrame]
        PicAck = 11                 '[繼續要圖]
        Login = 12                  '[登入PWD]
        PlayBack = 13               '[遠端放影]  
        QryTtlPtzFn = 14            '[詢問TTL, PTZ功能]
        CloseBack = 15              '[關閉遠端放影]
        QryTTLState = 16            '[詢問TTL目前狀態]
        CloseLive = 17              '[關閉看現場]
    End Enum
    ' 撥放控制
    Public Enum enumPlayCtrl As Integer
        FastBackward = 0
        Backward = 1
        [STOP] = 2
        Forward = 3
        FastForward = 4
        TimeSearch = 5
    End Enum

    <StructLayout(LayoutKind.Sequential)> _
    Public Structure BITMAPINFOHEADER '40 bytes
        Public biSize As Integer
        Public biWidth As Integer
        Public biHeight As Integer
        Public biPlanes As Short
        Public biBitCount As Short
        Public biCompression As Integer
        Public biSizeImage As Integer
        Public biXPelsPerMeter As Integer
        Public biYPelsPerMeter As Integer
        Public biClrUsed As Integer
        Public biClrImportant As Integer
    End Structure
    Public Class stCamData
        Public CamName As String                    '攝影機名稱
        Public CapturedUtc As Date                  '圖片時間
        Public DataLength As UInt32                 '圖片資料長度
        Public frameData() As Byte                  'frameData
        Public DecodeBmpData() As Byte              '解壓後的BMP資料(前一張BMP資料)
        Public PreBmpData() As Byte                 '前前一張BMP資料
        Public InitPrtBmpOk As Boolean              '一開始準備兩張一樣的黑色背景圖
    End Class
    Public Class stAlarmState
        Public State As Boolean                     '警報狀態
        Public Kind As Byte                         '警報類型
        Public AlmName As String                    '警報名稱
    End Class
    Public Class stVsdrData
        Public TotCh As UInt16                      '全部CH數量
        Public VsdrName As String                   'vsdr名稱
        Public VsdrGuid As String                   'vsdr GUID
        Public CamData() As stCamData
        Public Alarm() As stAlarmState
        Public InstId(3) As Byte                    'Instance Id
        Public InstPwd(3) As Byte                   'Instance Pwd
    End Class

    Private _PlayMode As enumPlayMode = enumPlayMode.LiveMode
    Private _VsdrData As stVsdrData = Nothing
    Private _defPicSize As Integer = (320 * 240 * 3)
    Private _BmpBackData() As Byte
    Private _defPwd As String = "99999999"
    Private _NowSelCh(3) As Byte  '目前選擇的ch on/off 狀態 32bit
    Private _syncPics As Object = Nothing
    Private _IsFullMode As Boolean = False
    Private _PicFull As PictureBox = Nothing
    Private _Pics() As PictureBox = Nothing
    Private _Lbls() As Label = Nothing
    Private _IP As String = ""
    Private _PORT As Integer
    Private _TTLFn As Boolean = False
    Private _PTZFn As Boolean = False


    '遠端HDD錄影時間
    Private UtcStart As Date = CDate("#1969/12/31 17:00:00#") '"#1970/1/1#"
    Private Sub RecRangeParser(ByRef bData() As Byte)
        If bData.Length < 57 Then Exit Sub
        If (bData(0) = &H2A) And _
           (bData(1) = &H18) And _
           (bData(2) = &H43) And _
           (bData(3) = &H1) Then

            '遠端掃描CH號碼
            Dim ScanCh As Byte = bData(42)

            '遠端掃描速度
            Dim ScanRate As Double = BitConverter.ToUInt32(New Byte() {bData(46), bData(47), bData(48), bData(49)}, 0) / 1000

            '錄影起始秒數
            Dim RecStSec As UInt32 = BitConverter.ToUInt32(New Byte() {bData(50), bData(51), bData(52), bData(53)}, 0)

            '錄影結束秒數
            Dim RecEndSec As UInt32 = BitConverter.ToUInt32(New Byte() {bData(54), bData(55), bData(56), bData(57)}, 0)

            '遠端錄影開始時間 = (傳回總秒數 + 1970/1/1 00:00:00 - 7小時)
            Dim RecStUtc As Date = DateAdd(DateInterval.Second, RecStSec, UtcStart)

            '遠端錄影結束時間
            Dim RecEndUtc As Date = DateAdd(DateInterval.Second, RecEndSec, UtcStart)

            '遠端硬碟錄影空間
            Dim HddPresent As Single = BitConverter.ToUInt16(New Byte() {bData(58), bData(59)}, 0) / 100
            RaiseEvent RecRange(Me, ScanCh, ScanRate, RecStUtc, RecEndUtc, HddPresent)
        End If
    End Sub
    ' 檢查連線狀態
    Private Sub checkConnect()
        SyncLock Me._syncSock
            If IsNothing(Me._mySock) Then
                Console.WriteLine(" 檢查連線狀態 Me._mySock = New clsWinSock")
                Me._mySock = New clsWinSock
                Me._mySock.Connect(Me._IP, Me._PORT)
                ' SOCK 嘗試連線中
                RaiseEvent SckTryConnect(Me, Me._IP, Me._PORT)
            End If
        End SyncLock
    End Sub
    ' 顯示時間
    Private _LastLbl As Label = Nothing
    Private Delegate Sub ivk_ShowTime(ByVal sender As Label, ByVal txt As String)
    Private Sub ShowTime(ByVal sender As Label, ByVal txt As String)
        If IsNothing(sender) = False Then
            If IsNothing(Me._LastLbl) = False Then
                Me._LastLbl.ForeColor = Color.Navy
            End If
            Me._LastLbl = sender
            Me._LastLbl.ForeColor = Color.Red
            Me._LastLbl.Text = txt
        End If
    End Sub
    ' vsvc 解壓
    Private Sub deCompressVsvc(ByRef cmd2A1843() As Byte)

        '解壓縮vsvc圖片
        Dim BiInHeader As BITMAPINFOHEADER
        With BiInHeader
            .biSize = 40
            .biWidth = 320
            .biHeight = 240
            .biPlanes = 1
            .biBitCount = 24
            .biCompression = 1668707190
        End With



        '取出這CH編號
        Dim ThisChNo As Byte = cmd2A1843(&H2E)


        '如果大於16ch,離開
        If ThisChNo < 16 Then

            ' 如果要看這CH
            If (Me._SelCh And (2 ^ ThisChNo)) = (2 ^ ThisChNo) Then
                ''---------- TEST ------------
                'Static cnt As UInteger
                'If cmd2A1843(16) = &H6 Then
                '    Dim fname As String = "c:\test\" & cnt.ToString & ".bin"
                '    My.Computer.FileSystem.WriteAllBytes(fname, cmd2A1843, False)
                '    cnt += 1
                'End If
                ''---------- TEST ------------

                '圖片時間總秒數
                Dim CapturedTime_T As UInt32 = BitConverter.ToUInt32(New Byte() {cmd2A1843(&H40), cmd2A1843(&H41), cmd2A1843(&H42), cmd2A1843(&H43)}, 0)
                '圖片資料長度
                Dim tmpDataLength As UInt32 = BitConverter.ToUInt32(New Byte() {cmd2A1843(&H44), cmd2A1843(&H45), cmd2A1843(&H46), cmd2A1843(&H47)}, 0)
                '圖片錄影時間
                Me._VsdrData.CamData(ThisChNo).CapturedUtc = DateAdd(DateInterval.Second, CapturedTime_T, UtcStart)

                'Console.WriteLine("CapturedUtc = {0}", Me._VsdrData.CamData(ThisChNo).CapturedUtc.ToString("yyyy/MM/dd HH:mm:ss"))

                ' ===== 如果是CKE MODE =====
                ' 如果在TimeSearch
                If Me._CKE_WaitSearech Then
                    If Me._VsdrData.CamData(ThisChNo).CapturedUtc >= Me._CKE_StTime Then
                        Me._CKE_SearechOK = True
                        Me._CKE_WaitSearech = False
                    End If
                End If
                ' 如果找到CKE要輸出的AVI時間
                If Me._CKE_SearechOK = True AndAlso Me._CKE_AviExportOK = False Then
                    If Me._VsdrData.CamData(ThisChNo).CapturedUtc >= Me._CKE_EndTime Then
                        Me._CKE_AviExportOK = True
                    End If
                End If
                ' ===== 如果是CKE MODE =====


                ' 顯示圖片時間
                Dim txtTime As String = ""
                With Me._VsdrData.CamData(ThisChNo)
                    If IsNothing(Me._Lbls) = False Then
                        'Dim txt As String = (ThisChNo + 1).ToString & "." & .CamName & "-" & .CapturedUtc.ToString("MM/dd/yyyy HH:mm:ss")
                        txtTime = (ThisChNo + 1).ToString & "." & .CamName & "-" & .CapturedUtc.ToString("MM/dd/yyyy HH:mm:ss")
                        Me._Lbls(ThisChNo).Invoke(New ivk_ShowTime(AddressOf ShowTime), Me._Lbls(ThisChNo), txtTime)
                    End If
                End With


                '檢查是否為KeyFrame
                Dim IsKeyFrame As Boolean = (cmd2A1843(cmd2A1843.Length - 1) <> 0) _
                                    AndAlso (cmd2A1843(cmd2A1843.Length - 2) <> 0) _
                                    AndAlso (cmd2A1843(cmd2A1843.Length - 3) <> 0) _
                                    AndAlso (cmd2A1843(cmd2A1843.Length - 4) <> 0)


                With Me._VsdrData.CamData(ThisChNo)
                    '如果是KeyFrame
                    If IsKeyFrame = True Then
                        '圖片資料長度
                        .DataLength = (tmpDataLength - &H8A)
                        '定義圖片空間大小
                        ReDim .frameData(.DataLength - 1)
                        '取出 KeyFrame Data
                        Array.Copy(cmd2A1843, &H48, .frameData, 0, .DataLength)
                        BiInHeader.biSizeImage = .DataLength
                        ''取出 BMP INFO HEADER
                        'Dim BmpHeaderStart As Integer = cmd2A1843.Length - 47
                        ''BmpHeaderStart = UBound(cmd2A1843) - 47
                        'Array.Copy(cmd2A1843, BmpHeaderStart, .BMPInfoHeader, 0, 40)
                        'BiInHeader = .BMPInfoHeader

                        '********** 解壓圖片 ************
                        Array.Copy(.DecodeBmpData, Me._BmpBackData, Me._defPicSize)
                        Try
                            If PHHCodec(BiInHeader, .frameData(0), .DecodeBmpData(0), .PreBmpData(0)) = 0 Then
                                ' ===== 如果是CKE MODE =====
                                Me.AddVideoFrame(Me._BmpBackData, Me._VsdrData.CamData(ThisChNo).CapturedUtc)
                                ' AVI 輸出進度
                                RaiseEvent CKE_AviExportIng(Me, Me._VsdrData.CamData(ThisChNo).CapturedUtc)
                                ' ===== 如果是CKE MODE =====

                                ' ===== 一般 AVI EXPORT =====
                                If Me._AviRec Then AddVideoFrame(ThisChNo, Me._BmpBackData, Me._VsdrData.CamData(ThisChNo).CapturedUtc)
                                ' ===== 一般 AVI EXPORT =====


                                '把這次回應BMP資料往前移
                                Array.Copy(Me._BmpBackData, .PreBmpData, Me._defPicSize)
                                ' 顯示圖片
                                SyncLock Me._syncPics
                                    If IsNothing(Me._Pics) = False Then
                                        If Me._IsFullMode Then
                                            clsDibImage.DrawDIB(Me._PicFull, .DecodeBmpData, txtTime)
                                        Else
                                            clsDibImage.DrawDIB(Me._Pics(ThisChNo), .DecodeBmpData, "")
                                        End If
                                    End If
                                End SyncLock
                            End If
                        Catch ex As Exception
                        End Try
                        '********** 解壓圖片 ************

                    Else
                        'Dim testCnt As Byte() = New Byte() {cmd2A1843(cmd2A1843.Length - 13), cmd2A1843(cmd2A1843.Length - 14), cmd2A1843(cmd2A1843.Length - 15), cmd2A1843(cmd2A1843.Length - 16)}
                        'Dim tCnt As UInteger = System.BitConverter.ToUInt32(testCnt, 0)
                        'Console.WriteLine("~~~~~~~~~>> {0}", tCnt)

                        '圖片資料長度
                        .DataLength = (tmpDataLength - &H22)
                        '定義圖片空間大小
                        ReDim .frameData(.DataLength - 1)
                        '取出 Frame Data
                        Array.Copy(cmd2A1843, &H48, .frameData, 0, .DataLength)
                        '設定 BMPHEADER 的biSizeImage
                        '.BMPInfoHeader.biSizeImage = .DataLength
                        BiInHeader.biSizeImage = .DataLength '.BMPInfoHeader


                        '********** 解壓圖片 ************
                        Array.Copy(.DecodeBmpData, Me._BmpBackData, Me._defPicSize)
                        '一開始準備兩張一樣的黑色背景圖
                        If .InitPrtBmpOk = False Then
                            '如果前前張圖片空白 , 填上前張圖片
                            If .PreBmpData(0) = 0 Then
                                '設定已經copy過旗號
                                .InitPrtBmpOk = True
                                Array.Copy(Me._BmpBackData, .PreBmpData, Me._defPicSize)
                            End If
                        End If
                        Try
                            If PHHCodec(BiInHeader, .frameData(0), .DecodeBmpData(0), .PreBmpData(0)) = 0 Then
                                ' ===== 如果是CKE MODE =====
                                Me.AddVideoFrame(Me._BmpBackData, Me._VsdrData.CamData(ThisChNo).CapturedUtc)
                                ' AVI 輸出進度
                                RaiseEvent CKE_AviExportIng(Me, Me._VsdrData.CamData(ThisChNo).CapturedUtc)
                                ' ===== 如果是CKE MODE =====

                                ' ===== 一般 AVI EXPORT =====
                                If Me._AviRec Then AddVideoFrame(ThisChNo, Me._BmpBackData, Me._VsdrData.CamData(ThisChNo).CapturedUtc)
                                ' ===== 一般 AVI EXPORT =====

                                '把這次回應BMP資料往前移
                                Array.Copy(Me._BmpBackData, .PreBmpData, Me._defPicSize)
                                ' 顯示圖片
                                SyncLock Me._syncPics
                                    If IsNothing(Me._Pics) = False Then
                                        If Me._IsFullMode Then
                                            clsDibImage.DrawDIB(Me._PicFull, .DecodeBmpData, txtTime)
                                        Else
                                            clsDibImage.DrawDIB(Me._Pics(ThisChNo), .DecodeBmpData, "")
                                        End If
                                    End If
                                End SyncLock
                            End If
                        Catch ex As Exception
                    End Try
                        '********** 解壓圖片 ************
                    End If
                End With

            End If
        End If
    End Sub
    ' 處理資料
    Private Sub DataWork()
        '取命令做事"2A 18 43"開頭
        Dim cmd2A1843() As Byte = Nothing
        Do While getCmd(cmd2A1843) = True

            '警報封包
            If cmd2A1843(3) = &H4 Then

                '警報CH
                Dim Ch As Byte = cmd2A1843(5)
                With Me._VsdrData.Alarm(Ch)
                    '設定警報狀態
                    .State = CBool(cmd2A1843(4))
                    '設定警報類型
                    .Kind = cmd2A1843(6)
                    ' 警報事件
                    RaiseEvent Alarm(Me, Ch, .Kind, .State)
                End With


            Else
                If cmd2A1843.Length < 19 Then Exit Sub
                '取命令格式
                Dim CmdStr As String = Hex(cmd2A1843(16)).PadLeft(2, "0") & _
                                       Hex(cmd2A1843(17)).PadLeft(2, "0") & _
                                       Hex(cmd2A1843(18)).PadLeft(2, "0") & _
                                       Hex(cmd2A1843(19)).PadLeft(2, "0")

                'If CmdStr <> "04000107" Then
                '    Console.WriteLine("... CmdStr => {0}", CmdStr)
                'End If

                Select Case CmdStr
                    Case "02000001" '回應TTL功能
                        Me._TTLFn = cmd2A1843(24) = 1

                    Case "03000001" '回應PTZ功能
                        Me._PTZFn = cmd2A1843(24) = 1

                    Case "04000103" '詢問本機名稱
                        If cmd2A1843(8) = &H14 Then
                            '回應本機名稱
                            cmdSend(enumCmd.SendLocalName)
                        End If

                    Case "04000003" '收到vsdr名稱
                        If cmd2A1843(8) = &H3E Then
                            'Dim tmpStr As String = System.Text.ASCIIEncoding.UTF8.GetString(cmd2A1843, &H2E, &H4C - &H2E)
                            Dim tmpStr As String = System.Text.Encoding.Default.GetString(cmd2A1843, &H2E, &H4C - &H2E)
                            Me._VsdrData.VsdrName = tmpStr.Replace(Chr(0), "")

                            '回應本機GUID
                            cmdSend(enumCmd.SendLocalGuid)
                        End If

                        '收到各CH資訊
                        If ((cmd2A1843(8) = &H2) Or (cmd2A1843(8) = &H92) Or (cmd2A1843(8) = &HDA)) And ((cmd2A1843(9) = &H17) Or (cmd2A1843(9) = &HB) Or (cmd2A1843(9) = &H5)) Then
                            '取TotCH數量
                            Me._VsdrData.TotCh = BitConverter.ToUInt16(New Byte() {cmd2A1843(&H2A), cmd2A1843(&H2B)}, 0) '- 1

                            '如果小於於15CH
                            If Me._VsdrData.TotCh <= 16 Then

                                '重新定義陣列大小
                                ReDim Me._VsdrData.CamData(Me._VsdrData.TotCh - 1)
                                ReDim Me._VsdrData.Alarm(Me._VsdrData.TotCh - 1)
                                For i As Integer = 0 To Me._VsdrData.TotCh - 1
                                    Me._VsdrData.CamData(i) = New stCamData
                                    Me._VsdrData.Alarm(i) = New stAlarmState
                                    ReDim Me._VsdrData.CamData(i).DecodeBmpData(Me._defPicSize - 1) '前一張BMP
                                    ReDim Me._VsdrData.CamData(i).PreBmpData(Me._defPicSize - 1)    '前前一張BMP

                                    ' 各攝影機名稱
                                    Dim tmpNameSt As Integer = (58 + i * 366)
                                    Dim tmpNameLeng As Integer = (80 + i * 366) - tmpNameSt
                                    'Dim bTEST(6) As Byte
                                    'bTEST(0) = &HC4
                                    'bTEST(1) = &HE1
                                    'bTEST(2) = &HBC
                                    'bTEST(3) = &H76
                                    'bTEST(4) = &HBE
                                    'bTEST(5) = &HF7
                                    'bTEST(6) = &H31
                                    'Dim ttt As String = System.Text.Encoding.Default.GetString(bTEST, 0, bTEST.Length)

                                    Dim tmpName As String = System.Text.Encoding.Default.GetString(cmd2A1843, tmpNameSt, tmpNameLeng)
                                    Me._VsdrData.CamData(i).CamName = tmpName.Replace(Chr(0), "")
                                Next

                                ' 遠端主機資訊
                                RaiseEvent VsdrInfo(Me, Me._IP, Me._PORT, Me._VsdrData.VsdrName, Me._VsdrData.TotCh)

                                '詢問各alm設定
                                cmdSend(enumCmd.QryAlarmSet)

                            End If '如果小於於15CH
                        End If '收到各CH資訊

                        '收到各alm設定
                        If cmd2A1843(8) = &H48 AndAlso ((cmd2A1843(9) = &H4) OrElse (cmd2A1843(9) = &H2) OrElse (cmd2A1843(9) = &H1)) Then
                            For i As Integer = 0 To Me._VsdrData.TotCh - 1
                                ' 各警報名稱
                                Dim tmpNameSt As Integer = (94 + i * 64)
                                Dim tmpNameLeng As Integer = (116 + i * 64) - tmpNameSt
                                'Dim tmpName As String = System.Text.ASCIIEncoding.UTF8.GetString(cmd2A1843, tmpNameSt, tmpNameLeng)
                                Dim tmpName As String = System.Text.Encoding.Default.GetString(cmd2A1843, tmpNameSt, tmpNameLeng)
                                Me._VsdrData.Alarm(i).AlmName = tmpName.Replace(Chr(0), "")
                            Next

                            RaiseEvent AlarmName(Me, Me._VsdrData.Alarm)
                            ''詢問InstId LiveView
                            'cmdSend(enumCmd.QryInstId)
                        End If

                    Case "E0000107" '收到vsdr-GUID
                        If cmd2A1843(8) = &HF4 Then
                            Dim tmpGuid As String = ""
                            For i As Integer = &H30 To &H55
                                tmpGuid &= Chr(cmd2A1843(i))
                            Next
                            Me._VsdrData.VsdrGuid = tmpGuid
                            '詢問各CH資訊
                            cmdSend(enumCmd.QryChInfo)
                        End If

                    Case "05000001", "06000001" '收到InstId(Live/PlayBack)

                        Console.WriteLine("... CmdStr => {0}", CmdStr)

                        If (cmd2A1843(8) = &H14) AndAlso (Me._PlayMode = cmd2A1843(16)) Then

                            '如果有使用權限
                            If (cmd2A1843(&H18) <> &H0) Then
                                Me._VsdrData.InstId(0) = cmd2A1843(&H14)
                                Me._VsdrData.InstId(1) = cmd2A1843(&H15)
                                Me._VsdrData.InstId(2) = cmd2A1843(&H16)
                                Me._VsdrData.InstId(3) = cmd2A1843(&H17)

                                Console.WriteLine("... CmdStr => 有使用權限")

                                ' 顯示影像視窗
                                RaiseEvent ShowVdoWindow(Me, cmd2A1843(16))
                                ''詢問要圖密碼
                                'cmdSend(enumCmd.QryPicPwd)

                            Else
                                '如果遠端playback有人使用
                                If (cmd2A1843(&H14) = &HFF) And _
                                   (cmd2A1843(&H15) = &HFF) And _
                                   (cmd2A1843(&H16) = &HFF) And _
                                   (cmd2A1843(&H17) = &HFF) Then

                                    Console.WriteLine("... CmdStr => 遠端playback有人使用")

                                    ' 切回LIVE
                                    Me.PlayMode = enumPlayMode.LiveMode
                                    ' playback有人使用
                                    RaiseEvent PlayBackUsing(Me, Me._IP, Me._PORT)

                                    ''再要InstId
                                    'cmdSend(enumCmd.QryInstId)
                                    ''離開
                                    'Exit Sub
                                Else
                                    ' 需要登入密碼事件
                                    RaiseEvent NeedLogin(Me)
                                    'Console.WriteLine("... CmdStr => 送出login PWD")
                                    ''送出login PWD
                                    'cmdSend(enumCmd.Login)
                                End If
                            End If
                        End If

                    Case "05000002", "06000002" '收到InstId PWD(Live/PlayBack)

                        Console.WriteLine("... CmdStr => {0}", CmdStr)

                        If cmd2A1843(&H18) <> 0 Then
                            Me._VsdrData.InstId(0) = cmd2A1843(&H14)
                            Me._VsdrData.InstId(1) = cmd2A1843(&H15)
                            Me._VsdrData.InstId(2) = cmd2A1843(&H16)
                            Me._VsdrData.InstId(3) = cmd2A1843(&H17)

                            ' 顯示影像視窗
                            RaiseEvent ShowVdoWindow(Me, cmd2A1843(16))
                            ''詢問要圖密碼
                            'cmdSend(enumCmd.QryPicPwd)

                        Else
                            ' 關閉sock連線
                            SockDispose()
                            'Login 失敗
                            RaiseEvent LoginFail(Me, Me._IP, Me._PORT)
                        End If


                    Case "05000003", "06000003" '收到要圖密碼(Live/PlayBack)

                        Console.WriteLine("... CmdStr => {0}", CmdStr)

                        If cmd2A1843(8) = &H32 Then
                            Me._VsdrData.InstPwd(0) = cmd2A1843(&H2C)
                            Me._VsdrData.InstPwd(1) = cmd2A1843(&H2D)
                            Me._VsdrData.InstPwd(2) = cmd2A1843(&H2E)
                            Me._VsdrData.InstPwd(3) = cmd2A1843(&H2F)

                            Console.WriteLine("... CmdStr => 詢問KeyFrame")

                            '詢問KeyFrame
                            cmdSend(enumCmd.QryKeyFrame)
                            '影像開關
                            cmdSend(enumCmd.VideoSel)
                        End If


                    Case "05000107" '收到圖片資料(Live)
                        If Me._PlayMode = cmd2A1843(16) Then
                            Me._AckFrameNum = 0
                            '解壓縮vsvc圖片
                            deCompressVsvc(cmd2A1843)
                            '繼續要圖
                            cmdSend(enumCmd.PicAck)
                        End If

                    Case "06000107" '收到圖片資料(PlayBack)
                        If Me._PlayMode = cmd2A1843(16) Then
                            Select Case cmd2A1843(22)
                                Case &H86       ' PlayBack State Pack
                                    Me._AckFrameNum = System.BitConverter.ToUInt32(cmd2A1843, 52)
                                    'Console.WriteLine(" --- Play Back State CurFrameNum = [{0}]", Me._AckFrameNum)
                                    '繼續要圖
                                    cmdSend(enumCmd.PicAck)

                                Case &H88       ' PlayBack Picture
                                    '解壓縮vsvc圖片
                                    deCompressVsvc(cmd2A1843)
                            End Select
                        End If


                    Case "04000107" '收到錄影進度
                        If cmd2A1843(8) = &H32 Then
                            If Me._VsdrData.TotCh > 0 Then
                                '顯示遠端HDD錄影時間
                                RecRangeParser(cmd2A1843)
                            End If
                        End If


                    Case "05000004" ' Live Mode Ready
                        Console.WriteLine("... CmdStr => {0}", CmdStr)
                        Me.ReadyMode = enumReadyMode.LiveReady
                        ' 詢問TTL & PTZ功能
                        Me.cmdSend(enumCmd.QryTtlPtzFn)

                    Case "06000004" ' PlayBack Mode Ready
                        Console.WriteLine("... CmdStr => {0}", CmdStr)
                        Me.ReadyMode = enumReadyMode.PlayBackReady

                    Case "05000013", "06000013" '收到關閉看現場(Live/PlayBack)

                        Console.WriteLine("... CmdStr => {0}", CmdStr)

                        ''正在PLAY BACK旗號
                        'If Me._PlayMode = enumPlayMode.BackMode Then
                        '    '繼續看現場
                        '    cmdSend(enumCmd.QryInstId)
                        'End If
                End Select

            End If '如果是發生警報

        Loop
    End Sub
    '取命令做事"2A 18 43"開頭
    Private Function getCmd(ByRef cmd2A1843() As Byte) As Boolean
        Dim stCode As Integer
        Dim getDataLen As Integer

        '找2A 18 43開頭
        For i As Integer = 0 To TcpBuffer.Length - 4

            '如果找到開頭碼
            If (Me.TcpBuffer(i) = &H2A) AndAlso _
               (Me.TcpBuffer(i + 1) = &H18) AndAlso _
               (Me.TcpBuffer(i + 2) = &H43) Then

                '命令開始位址
                stCode = i

                '如果命令長度位址不在,離開
                If (stCode + 10) >= Me.TcpBuffer.Length Then Exit Function

                '取命令長度
                getDataLen = BitConverter.ToInt32(New Byte() {TcpBuffer(stCode + 8), TcpBuffer(stCode + 9), TcpBuffer(stCode + 10), 0}, 0)

                '如果資料長度足夠
                If (getDataLen + 15) < (Me.TcpBuffer.Length - stCode) Then
                    '重新定義命令長度
                    ReDim cmd2A1843(getDataLen + 15)
                    '取出命令資料
                    Array.Copy(Me.TcpBuffer, 0, cmd2A1843, 0, cmd2A1843.Length)


                    '扣掉TcpBuffer裡面的命令資料
                    Dim oldTcpLen As Integer
                    Dim newTcpLen As Integer
                    Dim newTcpBuffer() As Byte
                    oldTcpLen = TcpBuffer.Length - stCode
                    newTcpLen = oldTcpLen - (getDataLen + 16)
                    If newTcpLen > 0 Then
                        ReDim newTcpBuffer(newTcpLen - 1)
                        Array.Copy(Me.TcpBuffer, cmd2A1843.Length, newTcpBuffer, 0, newTcpBuffer.Length)
                        Me.TcpBuffer = newTcpBuffer
                    Else
                        Array.Resize(Me.TcpBuffer, 0)
                    End If

                    '設定命令取出成功旗號
                    Return True

                End If '如果資料長度足夠
            End If '如果找到開頭碼
        Next
    End Function
    ' 傳送命令
    Private _AckFrameNum As UInt32 = 0
    Private Sub cmdSend(ByVal cmd As enumCmd)
        Dim SendCMD() As Byte = Nothing

        Select Case cmd
            Case enumCmd.QryTTLState
                ReDim SendCMD(&H23)
                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = &H2
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H3
                SendCMD(&H14) = &H0
                SendCMD(&H15) = &H0
                SendCMD(&H16) = &H0
                SendCMD(&H17) = &H0
                SendCMD(&H18) = &H81

            Case enumCmd.QryTtlPtzFn
                ReDim SendCMD(&H47)
                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = &H2
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H1

                SendCMD(&H24) = &H2A
                SendCMD(&H25) = &H18
                SendCMD(&H26) = &H43
                SendCMD(&H27) = &H1
                SendCMD(&H28) = &H14
                SendCMD(&H29) = &H0
                SendCMD(&H2A) = &H0
                SendCMD(&H2B) = &H0
                SendCMD(&H2C) = &H14
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0
                SendCMD(&H2F) = &H0

                SendCMD(&H30) = &HF4
                SendCMD(&H31) = &HFF
                SendCMD(&H32) = &HF8
                SendCMD(&H33) = &HD6
                SendCMD(&H34) = &H3
                SendCMD(&H35) = &H0
                SendCMD(&H36) = &H1
                SendCMD(&H37) = &H1

            Case enumCmd.CloseBack
                ReDim SendCMD(&H23)
                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = &H6
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H13
                SendCMD(&H14) = &H0
                SendCMD(&H15) = &H0
                SendCMD(&H16) = &H0
                SendCMD(&H17) = &H0
                SendCMD(&H18) = &H0
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H0
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0

            Case enumCmd.CloseLive
                ReDim SendCMD(&H23)
                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = &H5
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H13
                SendCMD(&H14) = Me._VsdrData.InstId(0)
                SendCMD(&H15) = Me._VsdrData.InstId(1)
                SendCMD(&H16) = Me._VsdrData.InstId(2)
                SendCMD(&H17) = Me._VsdrData.InstId(3)
                SendCMD(&H18) = &H0
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H0
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0

            Case enumCmd.PlayBack
                ' 關閉看現場
                cmdSend(enumCmd.CloseLive)

                ReDim SendCMD(&H23)
                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = &H6
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H1
                SendCMD(&H14) = &H0
                SendCMD(&H15) = &H0
                SendCMD(&H16) = &H0
                SendCMD(&H17) = &H0
                SendCMD(&H18) = &H0
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H1
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H1
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0

            Case enumCmd.SendLocalGuid '[連線]
                Dim NewGuid As String = "{" & Guid.NewGuid.ToString & "}"
                ReDim SendCMD(&H103)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &HF4
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HCC
                SendCMD(&HD) = &HBE
                SendCMD(&HE) = &H87
                SendCMD(&HF) = &H0

                SendCMD(&H10) = &HE0
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H7
                SendCMD(&H14) = &HE0
                SendCMD(&H15) = &H1
                SendCMD(&H16) = &H0
                SendCMD(&H17) = &H0
                SendCMD(&H18) = &H0
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H0
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &HE0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0
                SendCMD(&H24) = &HE0
                SendCMD(&H25) = &H0
                SendCMD(&H26) = &H0
                SendCMD(&H27) = &H0
                SendCMD(&H28) = &H1
                SendCMD(&H29) = &H0
                SendCMD(&H2A) = &H0
                SendCMD(&H2B) = &H0
                SendCMD(&H2C) = &H1
                SendCMD(&H2D) = &H0
                SendCMD(&H2E) = &H0
                SendCMD(&H2F) = &H0

                ' GUID = "{xxx-xxx-xx-xxx...}"
                'Dim bGuid() As Byte = System.Text.ASCIIEncoding.ASCII.GetBytes(NewGuid)
                Dim bGuid() As Byte = System.Text.Encoding.Default.GetBytes(NewGuid)
                'System.Text.Encoding.Default.GetString
                Array.Copy(bGuid, 0, SendCMD, &H30, bGuid.Length)

                SendCMD(&HB0) = &HEB
                SendCMD(&HB1) = &HA9
                SendCMD(&HB2) = &H2
                SendCMD(&HB3) = &H43
                SendCMD(&HB4) = &H80
                SendCMD(&HB5) = &H70
                SendCMD(&HB6) = &H0
                SendCMD(&HB7) = &H0
                SendCMD(&HB8) = &H1
                SendCMD(&HB9) = &H0
                SendCMD(&HBA) = &H1

            Case enumCmd.QryName '[詢問主機名稱]
                ReDim SendCMD(&H23)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = &H4
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H3
                SendCMD(&H14) = &H0
                SendCMD(&H15) = &H0
                SendCMD(&H16) = &H0
                SendCMD(&H17) = &H0
                SendCMD(&H18) = &H4
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H0
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0


            Case enumCmd.QryChInfo '[詢問各CH資訊]
                ReDim SendCMD(&H23)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = &H4
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H3
                SendCMD(&H14) = &H0
                SendCMD(&H15) = &H0
                SendCMD(&H16) = &H0
                SendCMD(&H17) = &H0
                SendCMD(&H18) = &H1
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H0
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0


            Case enumCmd.QryAlarmSet '[詢問各alm設定]
                ReDim SendCMD(&H23)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = &H4
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H3
                SendCMD(&H14) = &H0
                SendCMD(&H15) = &H0
                SendCMD(&H16) = &H0
                SendCMD(&H17) = &H0
                SendCMD(&H18) = &H2
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H0
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0

            Case enumCmd.SendLocalName '[傳送本機名稱]
                Dim myClientMachineAddressList As System.Net.IPHostEntry = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName())
                Dim LocalPcName As String = myClientMachineAddressList.HostName
                'Dim bLocalPcName() As Byte = System.Text.ASCIIEncoding.ASCII.GetBytes(LocalPcName)
                Dim bLocalPcName() As Byte = System.Text.Encoding.Default.GetBytes(LocalPcName)

                ReDim SendCMD(&H4D)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H3E
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HAE
                SendCMD(&HD) = &HB0
                SendCMD(&HE) = &H77
                SendCMD(&HF) = &H19

                SendCMD(&H10) = &H4
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H0
                SendCMD(&H13) = &H3
                SendCMD(&H14) = &H0
                SendCMD(&H15) = &H0
                SendCMD(&H16) = &H0
                SendCMD(&H17) = &H0
                SendCMD(&H18) = &H5
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H0
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H2A
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0
                SendCMD(&H24) = &H4
                SendCMD(&H25) = &H0
                SendCMD(&H26) = &H2A
                SendCMD(&H27) = &H0
                SendCMD(&H28) = &H0
                SendCMD(&H29) = &H0
                SendCMD(&H2A) = &HC0
                SendCMD(&H2B) = &HA8
                SendCMD(&H2C) = &H0
                SendCMD(&H2D) = &H64

                Dim NameLen As Integer = bLocalPcName.Length
                If NameLen > (&H4D - &H2D) Then
                    NameLen = (&H4D - &H2D)
                End If
                Array.Copy(bLocalPcName, 0, SendCMD, &H2E, NameLen)

                'SendCMD(&H2E) = &H61    ' local pc name
                'SendCMD(&H2F) = &H2D

                'SendCMD(&H30) = &H6C
                'SendCMD(&H31) = &H75
                'SendCMD(&H32) = &H6E


            Case enumCmd.QryLiveInstId '[詢問InstId]
                ReDim SendCMD(&H23)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = &H5
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H1
                SendCMD(&H14) = &H0
                SendCMD(&H15) = &H0
                SendCMD(&H16) = &H0
                SendCMD(&H17) = &H0
                SendCMD(&H18) = &H0
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H1
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H1
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0


            Case enumCmd.QryPicFormat '[詢問圖片格式]
                ReDim SendCMD(&H23)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = &H5
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H3
                SendCMD(&H14) = Me._VsdrData.InstId(0)
                SendCMD(&H15) = Me._VsdrData.InstId(1)
                SendCMD(&H16) = Me._VsdrData.InstId(2)
                SendCMD(&H17) = Me._VsdrData.InstId(3)
                SendCMD(&H18) = &H87
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H3
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0

            Case enumCmd.QryPicPwd '[詢問要圖密碼]
                ReDim SendCMD(&H23)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = Me._PlayMode
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H3
                SendCMD(&H14) = Me._VsdrData.InstId(0)
                SendCMD(&H15) = Me._VsdrData.InstId(1)
                SendCMD(&H16) = Me._VsdrData.InstId(2)
                SendCMD(&H17) = Me._VsdrData.InstId(3)
                SendCMD(&H18) = &H86
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H3
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0


            Case enumCmd.Login '[登入PWD]
                ReDim SendCMD(&HEB)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &HDC
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &H1D
                SendCMD(&HD) = &H39
                SendCMD(&HE) = &H1
                SendCMD(&HF) = &H65

                SendCMD(&H10) = Me._PlayMode
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H2
                SendCMD(&H14) = &H1
                SendCMD(&H15) = &H0
                SendCMD(&H16) = &H0
                SendCMD(&H17) = &H0
                SendCMD(&H18) = &H0
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H0
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H1
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0
                SendCMD(&H20) = &HC8
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0

                SendCMD(&H24) = &H0
                SendCMD(&H25) = &H0
                SendCMD(&H26) = &H0
                SendCMD(&H27) = &H0
                SendCMD(&H28) = &H0
                SendCMD(&H29) = &H0
                SendCMD(&H2A) = &H0
                SendCMD(&H2B) = &H0

                '********* 加密 *********
                Dim myUID(63) As Byte
                Dim myGRP(63) As Byte
                Dim myPWD() As Byte = System.Text.ASCIIEncoding.ASCII.GetBytes(Me._defPwd)
                ReDim Preserve myPWD(63)

                EncodeBuf(myUID(0), 63)
                EncodeBuf(myPWD(0), 63)
                EncodeBuf(myGRP(0), 63)

                '********* 加密 *********
                For i = 0 To 63
                    SendCMD(&H2C + i) = myUID(i)
                Next i
                For i = 0 To 63
                    SendCMD(&H6C + i) = myPWD(i)
                Next i
                For i = 0 To 63
                    SendCMD(&HAC + i) = myGRP(i)
                Next i


            Case enumCmd.QryKeyFrame '[詢問KeyFrame]
                ReDim SendCMD(&H23)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = Me._PlayMode
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H5
                SendCMD(&H14) = Me._VsdrData.InstId(0)
                SendCMD(&H15) = Me._VsdrData.InstId(1)
                SendCMD(&H16) = Me._VsdrData.InstId(2)
                SendCMD(&H17) = Me._VsdrData.InstId(3)
                SendCMD(&H18) = &H81
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H3
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0

            Case enumCmd.VideoSel '[要求ch0~TotCh資料]
                ReDim SendCMD(&H41)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H32
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &H16
                SendCMD(&HD) = &HF
                SendCMD(&HE) = &HA1
                SendCMD(&HF) = &H53

                SendCMD(&H10) = Me._PlayMode
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H4
                SendCMD(&H14) = Me._VsdrData.InstId(0)
                SendCMD(&H15) = Me._VsdrData.InstId(1)
                SendCMD(&H16) = Me._VsdrData.InstId(2)
                SendCMD(&H17) = Me._VsdrData.InstId(3)
                SendCMD(&H18) = &H86
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H3
                SendCMD(&H1B) = &H0
                SendCMD(&H1C) = &H0
                SendCMD(&H1D) = &H0
                SendCMD(&H1E) = &H0
                SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H1E
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0
                SendCMD(&H24) = &H86
                SendCMD(&H25) = &H0
                SendCMD(&H26) = &H1E
                SendCMD(&H27) = &H0
                SendCMD(&H28) = &H0
                SendCMD(&H29) = &H0
                SendCMD(&H2A) = &H18
                SendCMD(&H2B) = &H0
                SendCMD(&H2C) = &HE0
                SendCMD(&H2D) = &H19

                '影像開關----------
                SendCMD(&H2E) = Me._NowSelCh(0) '32bit 代表32ch on/off
                SendCMD(&H2F) = Me._NowSelCh(1) '32bit 代表32ch on/off
                SendCMD(&H30) = Me._NowSelCh(2) '32bit 代表32ch on/off
                SendCMD(&H31) = Me._NowSelCh(3) '32bit 代表32ch on/off
                '影像開關----------

                SendCMD(&H32) = &HFF
                SendCMD(&H33) = &HFF
                SendCMD(&H34) = &H0
                SendCMD(&H35) = &H0
                SendCMD(&H36) = &H0
                SendCMD(&H37) = &H0
                SendCMD(&H38) = &H0
                SendCMD(&H39) = &H0
                SendCMD(&H3A) = &H0
                SendCMD(&H3B) = &H0
                SendCMD(&H3C) = Me._VsdrData.InstPwd(0)
                SendCMD(&H3D) = Me._VsdrData.InstPwd(1)
                SendCMD(&H3E) = Me._VsdrData.InstPwd(2)
                SendCMD(&H3F) = Me._VsdrData.InstPwd(3)

                SendCMD(&H40) = &H0
                SendCMD(&H41) = &H0


            Case enumCmd.PicAck '[繼續要圖]
                ReDim SendCMD(&H23)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H1
                SendCMD(&H4) = &H14
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H14
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &HF4
                SendCMD(&HD) = &HFF
                SendCMD(&HE) = &HF8
                SendCMD(&HF) = &HD6

                SendCMD(&H10) = Me._PlayMode
                SendCMD(&H11) = &H0
                SendCMD(&H12) = &H1
                SendCMD(&H13) = &H5
                SendCMD(&H14) = Me._VsdrData.InstId(0)
                SendCMD(&H15) = Me._VsdrData.InstId(1)
                SendCMD(&H16) = Me._VsdrData.InstId(2)
                SendCMD(&H17) = Me._VsdrData.InstId(3)
                SendCMD(&H18) = &H80
                SendCMD(&H19) = &H0
                SendCMD(&H1A) = &H1
                SendCMD(&H1B) = &H0

                ' Ack PlayBack Frame Number(4bytes)
                If Me._AckFrameNum > 0 Then
                    Dim bAck() As Byte = BitConverter.GetBytes(Me._AckFrameNum)
                    SendCMD(&H1C) = bAck(0)
                    SendCMD(&H1D) = bAck(1)
                    SendCMD(&H1E) = bAck(2)
                    SendCMD(&H1F) = bAck(3)
                End If
                'SendCMD(&H1C) = &H0     ' Ack Frame No(4bytes)
                'SendCMD(&H1D) = &H0
                'SendCMD(&H1E) = &H0
                'SendCMD(&H1F) = &H0

                SendCMD(&H20) = &H0
                SendCMD(&H21) = &H0
                SendCMD(&H22) = &H0
                SendCMD(&H23) = &H0


            Case enumCmd.DisConnect '斷線
                ReDim SendCMD(&HF)

                SendCMD(&H0) = &H2A
                SendCMD(&H1) = &H18
                SendCMD(&H2) = &H43
                SendCMD(&H3) = &H5
                SendCMD(&H4) = &HFE
                SendCMD(&H5) = &H0
                SendCMD(&H6) = &H0
                SendCMD(&H7) = &H0
                SendCMD(&H8) = &H0
                SendCMD(&H9) = &H0
                SendCMD(&HA) = &H0
                SendCMD(&HB) = &H0
                SendCMD(&HC) = &H99
                SendCMD(&HD) = &H57
                SendCMD(&HE) = &H7F
                SendCMD(&HF) = &H46
        End Select

        '如果為連線狀態
        If IsNothing(Me._mySock) = False AndAlso Me._mySock.Connected Then
            '傳送資料
            Me._mySock.Send(SendCMD)
        End If
    End Sub
    ' NEW
    Public Sub New()
        Dim rtnVal As Boolean = OpenPHHCodec
        Erase Me.TcpBuffer
        Me._syncPics = New Object
        Me._syncSock = New Object
        Me._VsdrData = New stVsdrData
        ReDim Me._BmpBackData(Me._defPicSize - 1)
    End Sub
End Class



